﻿using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework.Input;
using System.Linq;
using System.Text;
using tactics.GUI;

using tactics.Abilities;

namespace tactics
{
    using Coord = Utility.Pair<int, int>;

    public enum SelectionType
    {
        None,
        Unit,
        Ability,
        HoverUnit,
        HoverAbility
    }

    public class SelectionManager
    {
        private SelectionType currentMode;
        private ISelectionMode selectionMode;

        private Unit targetInFocus;
        private Player targetOwner;

        private Ability abilityInUse;

        private bool allowMouseUpdates;

        private Func<Unit, Dictionary<int, int>> getUnitMoveMatrixFunc;
        private Func<Unit, Player, Ability, Dictionary<int, int>> getAbilityAreaMatrixFunc;

        public bool MouseUpdatesAllowed
        {
            get { return allowMouseUpdates; }
        }

        public Ability AbilityInUse
        {
            get { return abilityInUse; }
            set { abilityInUse = value; }
        }

        public Unit UnitInFocus
        {
            get
            {
                if (selectionMode != null)
                    return selectionMode.SelectedUnit;
                return null;
            }
        }

        public Unit TargetInFocus
        {
            get { return targetInFocus; }
        }

        public Player UnitInFocusOwner
        {
            get 
            {
                if (selectionMode != null)
                    return selectionMode.UnitOwner;
                else
                    return null;
            }
        }

        public Player TargetInFocusOwner
        {
            get
            {
                if (selectionMode != null)
                    return selectionMode.UnitOwner;
                else
                    return null;
            }
        }

        public SelectionType Selection
        {
            get { return currentMode; }
        }

        public SelectionManager(Func<Unit, Dictionary<int, int>> getUnitMoveMatrixFuncIn, Func<Unit, Player, Ability, Dictionary<int, int>> getAbilityAreaMatrixFuncIn)
        {
            currentMode = SelectionType.None;

            getUnitMoveMatrixFunc = getUnitMoveMatrixFuncIn;
            getAbilityAreaMatrixFunc = getAbilityAreaMatrixFuncIn;

            selectionMode = null;
            targetInFocus = null;
            targetOwner = null;
            abilityInUse = null;

            allowMouseUpdates = true;
        }

        public void ClickUnit(Unit unit, Player player)
        {
            if (currentMode == SelectionType.Unit || currentMode == SelectionType.Ability)
            {
                ISelectionMode newSelectionMode = selectionMode.ClickUnit(unit, player);

                if (selectionMode != newSelectionMode)
                {
                    selectionMode = newSelectionMode;
                }
            }
            else
            {
                if (player == TacticsEngine.Instance.Game.TurnManager.CurrentPlayer && !(unit.Acted && unit.Moved))
                {
                    if (TacticsEngine.Instance.Game.TurnManager.UnitTurn == null ||
                        TacticsEngine.Instance.Game.TurnManager.UnitTurn == unit)
                    {
                        selectionMode = new UnitSelected(unit, player, getUnitMoveMatrixFunc);
                        currentMode = SelectionType.Unit;
                    }
                    else
                        HoverUnit(unit, player);
                }
            }

            if (selectionMode == null)
                currentMode = SelectionType.None;
        }

        public void HoverUnit(Unit unit, Player player)
        {
            if (selectionMode == null)
            {
                selectionMode = new UnitSelected(unit, player, getUnitMoveMatrixFunc);
                currentMode = SelectionType.HoverUnit;
            }
            else if (currentMode == SelectionType.Unit ||
                     currentMode == SelectionType.Ability)
            {
                targetInFocus = unit;
                targetOwner = player;
            }
        }

        public void ClickNothing(Coord coord)
        {
            if (currentMode == SelectionType.Unit)
            {
                selectionMode = selectionMode.ClickNothing(coord);

                // moved unit or deselected
                if (selectionMode == null)
                {
                    currentMode = SelectionType.None;
                }
            }
            else if (currentMode == SelectionType.Ability)
            {
                ISelectionMode newSelectionMode = selectionMode.ClickNothing(coord);

                if (selectionMode != newSelectionMode)
                {
                    selectionMode = newSelectionMode;
                }

                // deselected
                if (selectionMode == null)
                {
                    currentMode = SelectionType.None;
                    abilityInUse = null;
                }
            }
        }

        public void HoverNothing()
        {
            if (currentMode == SelectionType.HoverUnit)
            {
                selectionMode = null;
                currentMode = SelectionType.None;
            }

            targetInFocus = null;
        }

        public void RightClick()
        {
            currentMode = SelectionType.None;
            targetInFocus = null;
            targetOwner = null;
            selectionMode = null;
            abilityInUse = null;
        }

        public void SetAbilityToUse(Ability ability)
        {
            // don't bother doing this if there is no unit selected
            if (selectionMode != null &&
                !TacticsEngine.Instance.Game.TurnManager.AbilityUsed)
            {
                foreach (UnitShared.UnitTemplate.AbilityUses uses in selectionMode.SelectedUnit.Abilities)
                {
                    // if unit has this ability (sanity check)
                    if (uses.Id == ability.Id)
                    {
                        // switch to ability mode
                        selectionMode = new AbilitySelected(selectionMode.SelectedUnit, selectionMode.UnitOwner, ability, getUnitMoveMatrixFunc, getAbilityAreaMatrixFunc);
                        currentMode = SelectionType.Ability;
                        abilityInUse = ability;
                    }
                }
            }
        }

        public Dictionary<int, int> GetHighlightArea()
        {
            if (selectionMode != null)
                return selectionMode.GetHighlightArea();
            return new Dictionary<int, int>();
        }
    }
}
